/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package estructurassa.controladores.prediccionDemanda.promedioMovilPonderado;

import autocompletar.logica.ModeloAutoCompletar;
import estructurassa.DTOs.DTOPromedioMovilPonderado;
import estructurassa.controladores.Controlador;
import estructurassa.controladores.ControladorPrincipal;
import estructurassa.controladores.FabricaControladores;
import estructurassa.entidades.Demanda;
import estructurassa.entidades.ProductoTerminado;
import estructurassa.expertos.ExpertoABMProductoTerminado;
import estructurassa.expertos.ExpertoDemanda;
import estructurassa.expertos.FabricaExpertos;
import estructurassa.utiles.modeloTabla.ModeloTabla;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JInternalFrame;
import javax.swing.JOptionPane;

/**
 *
 * @author diego
 */
public class ControladorPredicionDemandaPromMovPond implements Controlador {

    private PantallaPrediccionPromedioMovilPonderado pantalla;
    private ExpertoDemanda experto;
    private boolean iniciado = false;
    private ProductoTerminado productoSeleccionado;
    private Float pesoAcumulado = 1f;

    public ControladorPredicionDemandaPromMovPond() {
        pantalla = new PantallaPrediccionPromedioMovilPonderado();
        experto = (ExpertoDemanda) FabricaExpertos.getInstancia().getExperto(FabricaExpertos.expertos.PREDICCION_DEMANDA);

        pantalla.getTblPeriodos().setModel(new ModeloTablaDemandaPromedioMovPonderado());

        pantalla.getBtnSeleccionarProducto().addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                seleccionarProducto();
            }
        });
        pantalla.getBtnSalir().addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                pantalla.setVisible(false);
            }
        });
        pantalla.getCbxCantidadPeriodo().addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (pantalla.getCbxCantidadPeriodo().getSelectedIndex() > 0) {
                    mostrarPeriodos();
                }
            }
        });
        pantalla.getTblPeriodos().addKeyListener(new KeyAdapter() {
            @Override
            public void keyReleased(KeyEvent e) {
                if (e.getKeyCode() == KeyEvent.VK_ENTER) {
                    recalcularPesos();
                }
            }
        });
    }

    @Override
    public JInternalFrame getPantalla() {
        return pantalla;
    }

    @Override
    public void iniciar() {
        if (!iniciado) {
            ((ControladorPrincipal) FabricaControladores.getInstance().getControlador(FabricaControladores.controladoresNombre.PRINCIPAL)).agregarPantallaInterna(pantalla);
        }
        List productos = ((ExpertoABMProductoTerminado) FabricaExpertos.getInstancia().getExperto(FabricaExpertos.expertos.ABM_PRODUCTO_TERMINADO)).buscarProductosTerminados();
        pantalla.getAutoCompletarTextField1().setModelo(new ModeloAutoCompletar(productos));
        pantalla.setVisible(true);
    }

    private void seleccionarProducto() {
        if (pantalla.getAutoCompletarTextField1().getItemSeleccionado() != null) {
            productoSeleccionado = (ProductoTerminado) pantalla.getAutoCompletarTextField1().getItemSeleccionado();
        }
        calcularPeriodos();
    }

    private void calcularPeriodos() {
        int cantidadPeriodos = productoSeleccionado.getHistoricoDemanda().size();
        ((DefaultComboBoxModel) pantalla.getCbxCantidadPeriodo().getModel()).removeAllElements();
        for (int i = 0; i < cantidadPeriodos; i++) {
            ((DefaultComboBoxModel) pantalla.getCbxCantidadPeriodo().getModel()).addElement(String.valueOf(i+1));
        }

    }

    private void mostrarPeriodos() {
        int cantPeriodos = Integer.valueOf(pantalla.getCbxCantidadPeriodo().getSelectedItem().toString());
        Calendar calendario = Calendar.getInstance();
        int mesActual = calendario.get(Calendar.MONTH);
        int anioActual = calendario.get(Calendar.YEAR);
        List dtosPeriodos = new ArrayList();
        for (int i = 0; i < cantPeriodos; i++) {
            int mes = mesActual - i;
            int anio = anioActual;
            if (mesActual == 1) {
                anio = anioActual - 1;
                mes = 12;
            }
            Demanda demanda = getDemanda(anio, mes, productoSeleccionado.getHistoricoDemanda());
            DTOPromedioMovilPonderado dto = new DTOPromedioMovilPonderado();
            dto.setAnio(demanda.getAnio());
            dto.setMes(demanda.getMes());
            dto.setPeso(1f / cantPeriodos);
            dtosPeriodos.add(dto);
        }
        ((ModeloTabla) pantalla.getTblPeriodos().getModel()).setListaElementos(dtosPeriodos);
    }

    private Demanda getDemanda(int anio, int mes, List<Demanda> demandas) {
        for (Demanda demanda : demandas) {
            if (demanda.getAnio() == anio && demanda.getMes() == mes) {
                return demanda;
            }
        }
        return null;
    }

    private void recalcularPesos() {
        int fila = pantalla.getTblPeriodos().getSelectedRow();
        ((DTOPromedioMovilPonderado) ((ModeloTablaDemandaPromedioMovPonderado) pantalla.getTblPeriodos().getModel()).getRow(fila)).setCambiado(true);
        Float ultimoPeso = ((DTOPromedioMovilPonderado) ((ModeloTablaDemandaPromedioMovPonderado) pantalla.getTblPeriodos().getModel()).getRow(fila)).getPeso();

        if (ultimoPeso < pesoAcumulado) {
            pesoAcumulado -= ultimoPeso;
            List periodos = ((ModeloTablaDemandaPromedioMovPonderado) pantalla.getTblPeriodos().getModel()).getListaElementos();
            int cantidadCambiados = 0;
            for (Object object : periodos) {
                DTOPromedioMovilPonderado dto = (DTOPromedioMovilPonderado) object;
                if (dto.isCambiado()) {
                    cantidadCambiados++;
                }
            }

            Float pesoDividido = pesoAcumulado / (periodos.size() - cantidadCambiados);
            pesoDividido = Redondear(pesoDividido, 3);
            for (Object object : periodos) {
                DTOPromedioMovilPonderado dto = (DTOPromedioMovilPonderado) object;
                if (dto.getPeso() != ultimoPeso && !dto.isCambiado()) {
                    dto.setPeso(pesoDividido);
                }
            }
        }
        if (!isPesoValido()) {
            JOptionPane.showMessageDialog(pantalla, "La sumatoria de los pesos no puede ser mayor a 1");
        }
        pesoAcumulado = 1f;
    }

    private boolean isPesoValido() {
        List periodos = ((ModeloTablaDemandaPromedioMovPonderado) pantalla.getTblPeriodos().getModel()).getListaElementos();
        Float total = 0f;
        for (Object object : periodos) {
            DTOPromedioMovilPonderado dto = (DTOPromedioMovilPonderado) object;
            total += dto.getPeso();
        }
        if (total <= 1) {
            return true;
        } else {
            return false;
        }
    }

    public Float Redondear(Float numero, int digitos) {
        int cifras = (int) Math.pow(10, digitos);
        Double valRedondeado = Math.rint(numero * cifras) / cifras;
        Float retorno = valRedondeado.floatValue();
        return retorno;
    }
}
